import crypto from 'crypto';
import { Logger, TopPayError, ErrorCode } from '../utils/logger';

// TopPay配置接口
export interface TopPayConfig {
  merchantCode: string;
  privateKey: string;
  publicKey: string;
  apiUrl: string; // 充值订单URL
  payoutApiUrl?: string; // 代付订单URL，可选（有默认值）
  notifyUrl?: string; // 回调地址可选
  mchUserId?: string; // 商户用户ID可选
}

// 创建订单请求参数
export interface CreateOrderRequest {
  userId: number;
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  transAccNo: string; // 银行卡号（所有支付方式都必填）
  paymentName: string; // 付款人真实名称（TopPay要求必填）
  bankCode: string; // 银行编码（所有支付方式都必填）
  extendParam?: string; // 透传参数（上传的内容会原路返回）
}

// 创建提现订单请求参数
export interface CreatePayoutOrderRequest {
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  receiverName: string; // 收款人姓名（必填）
  receiverBankCard: string; // 收款银行卡号（必填）
  bankCode: string; // 银行编码（必填）
  remark?: string; // 支付备注
}

// TopPay API响应
export interface TopPayResponse {
  platRespCode: string;
  platRespMessage: string;
  platOrderNum?: string;
  orderNum?: string;
  payMoney?: string;
  payFee?: string;
  url?: string;
  payData?: string;
  bankName?: string;
  custAccName?: string;
  paymentName?: string;
  extendParam?: string;
}

// TopPay查询订单响应
export interface TopPayQueryResponse {
  success: boolean;
  code: number;
  message: string;
  data?: {
    msg: string;
    platOrderNum: string;
    amount: string;
    fee: string;
    orderNum: string;
    inAddress?: string;
    sendAddress?: string;
    platRespCode: string;
    platRespMessage: string;
    status: string | number;
  };
}

// 异步通知数据
export interface TopPayNotification {
  code: string;
  msg: string;
  status: string;
  method: string;
  platOrderNum: string;
  orderNum: string;
  payMoney: string;
  payFee: string;
  transAccNo?: string;
  paymentName?: string;
  extendParam?: string;
  platSign: string;
}

export class TopPayService {
  private config: TopPayConfig;

  constructor(config: TopPayConfig) {
    this.config = config;
  }

  /**
   * RSA私钥签名 - 使用TopPay要求的私钥加密方式
   */
  private signWithPrivateKey(data: string): string {
    try {
      Logger.debug('开始生成签名', { dataLength: data.length });

      // 处理私钥格式 - 支持多种格式
      let privateKey = this.config.privateKey.trim();

      // 如果私钥没有包含PEM头尾，则添加
      if (!privateKey.includes('-----BEGIN')) {
        privateKey = `-----BEGIN PRIVATE KEY-----\n${privateKey}\n-----END PRIVATE KEY-----`;
      }

      // TopPay使用RSA私钥加密而不是签名
      const keyObject = crypto.createPrivateKey(privateKey);

      // 分块加密（RSA有长度限制）
      const maxBlockSize = 117; // RSA 1024位密钥的最大加密块大小
      const dataBuffer = Buffer.from(data, 'utf8');
      const encrypted = [];

      for (let i = 0; i < dataBuffer.length; i += maxBlockSize) {
        const chunk = dataBuffer.subarray(i, i + maxBlockSize);
        const encryptedChunk = crypto.privateEncrypt(keyObject, chunk);
        encrypted.push(encryptedChunk);
      }

      const signature = Buffer.concat(encrypted).toString('base64');
      Logger.debug('签名生成成功', { signatureLength: signature.length });

      return signature;
    } catch (error) {
      Logger.error('签名生成失败', error, { dataLength: data.length });
      throw new TopPayError(`签名失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * RSA公钥解密验签 - 按照TopPay文档要求使用公钥解密方式验签
   */
  private verifyWithPublicKey(data: string, signature: string): boolean {
    try {
      Logger.debug('开始验证签名', {
        dataLength: data.length,
        signatureLength: signature.length
      });

      // 处理公钥格式 - 支持多种格式
      let publicKey = this.config.publicKey.trim();

      // 如果公钥没有包含PEM头尾，则添加
      if (!publicKey.includes('-----BEGIN')) {
        publicKey = `-----BEGIN PUBLIC KEY-----\n${publicKey}\n-----END PUBLIC KEY-----`;
      }

      const keyObject = crypto.createPublicKey(publicKey);

      // 解码签名
      const signatureBuffer = Buffer.from(signature, 'base64');

      // 分块解密（RSA有长度限制）
      const maxBlockSize = 128; // RSA 1024位密钥的最大解密块大小
      const decrypted = [];

      for (let i = 0; i < signatureBuffer.length; i += maxBlockSize) {
        const chunk = signatureBuffer.subarray(i, i + maxBlockSize);
        const decryptedChunk = crypto.publicDecrypt(keyObject, chunk);
        decrypted.push(decryptedChunk);
      }

      const decryptedData = Buffer.concat(decrypted).toString('utf8');
      const isValid = decryptedData === data;

      Logger.debug('签名验证完成', {
        isValid,
        decryptedDataLength: decryptedData.length
      });

      return isValid;
    } catch (error) {
      Logger.error('签名验证失败', error, {
        dataLength: data.length,
        signatureLength: signature.length
      });
      return false;
    }
  }

  /**
   * 验证创建订单请求参数
   */
  private validateCreateOrderRequest(request: CreateOrderRequest): void {
    Logger.debug('开始验证订单创建参数', {
      orderId: request.orderId,
      paymentMethod: request.paymentMethod,
      amount: request.amount
    });

    if (!request.paymentName || request.paymentName.trim() === '') {
      throw new TopPayError('付款人真实名称(paymentName)是必填项', { orderId: request.orderId });
    }

    // 银行卡号对所有支付方式都是必填的
    if (!request.transAccNo || request.transAccNo.trim() === '') {
      throw new TopPayError('银行卡号(transAccNo)是必填项', {
        orderId: request.orderId,
        paymentMethod: request.paymentMethod
      });
    }

    // 验证银行卡号格式（基本验证）
    if (!/^\d{10,20}$/.test(request.transAccNo)) {
      throw new TopPayError('银行卡号格式不正确，应为10-20位数字', {
        orderId: request.orderId,
        transAccNo: request.transAccNo?.substring(0, 4) + '****' // 只记录前4位
      });
    }

    // 银行编码对所有支付方式都是必填的
    if (!request.bankCode || request.bankCode.trim() === '') {
      throw new TopPayError('银行编码(bankCode)是必填项', {
        orderId: request.orderId,
        paymentMethod: request.paymentMethod
      });
    }

    if (request.amount <= 0) {
      throw new TopPayError('充值金额必须大于0', {
        orderId: request.orderId,
        amount: request.amount
      });
    }

    // 验证金额精度（TopPay支持两位小数）
    if (!/^\d+(\.\d{1,2})?$/.test(request.amount.toString())) {
      throw new TopPayError('充值金额最多支持两位小数', {
        orderId: request.orderId,
        amount: request.amount
      });
    }

    Logger.debug('订单创建参数验证通过', { orderId: request.orderId });
  }

  /**
   * 生成订单号
   */
  generateOrderId(): string {
    return `TG${Date.now()}${Math.random().toString(36).substring(2, 6).toUpperCase()}`;
  }

  /**
   * 创建充值订单
   */
  async createRechargeOrder(request: CreateOrderRequest): Promise<TopPayResponse> {
    // 参数验证
    this.validateCreateOrderRequest(request);

    const params: any = {
      merchantCode: this.config.merchantCode,
      orderType: '0', // 法币(泰铢)交易
      orderNum: request.orderId,
      payMoney: request.amount.toFixed(2),
      paymentName: request.paymentName, // TopPay要求必填
      dateTime: this.formatDateTime(new Date()),
    };

    // TopPay要求必须提供notifyUrl参数
    if (!this.config.notifyUrl) {
      throw new Error('notifyUrl未配置，请在环境变量中设置TOPPAY_NOTIFY_URL');
    }
    params.notifyUrl = this.config.notifyUrl;

    // 处理支付方式和相关参数
    if (request.paymentMethod) {
      params.method = request.paymentMethod;
    }

    // 处理银行卡号和银行编码 - 所有支付方式都需要
    // 银行卡号（必填）
    params.transAccNo = request.transAccNo;

    // 银行编码（必填）
    params.bankCode = request.bankCode;

    // 透传参数（可选）
    if (request.extendParam) {
      params.extendParam = request.extendParam;
    }

    // 按ASCII排序并拼接参数值
    const sortedKeys = Object.keys(params).sort();
    const signString = sortedKeys.map(key => params[key as keyof typeof params]).join('');

    // 生成签名
    const sign = this.signWithPrivateKey(signString);

    const requestData = {
      ...params,
      sign,
    };

    Logger.topPayRequest('创建订单', {
      merchantCode: this.config.merchantCode,
      orderNum: requestData.orderNum,
      payMoney: requestData.payMoney,
      method: requestData.method,
      paymentName: requestData.paymentName
    }, { orderId: request.orderId });
    try {
      const response = await fetch(this.config.apiUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestData),
      });

      Logger.debug('TopPay HTTP响应状态', {
        status: response.status,
        orderId: request.orderId
      });

      const responseText = await response.text();

      if (!response.ok) {
        Logger.topPayError('创建订单HTTP错误', new Error(`HTTP ${response.status}`), {
          orderId: request.orderId,
          status: response.status,
          responseBody: responseText
        });
        throw new TopPayError(`TopPay API HTTP错误: ${response.status}`, {
          orderId: request.orderId,
          status: response.status
        });
      }

      try {
        const result: TopPayResponse = JSON.parse(responseText);

        Logger.topPayResponse('创建订单', result, {
          orderId: request.orderId,
          platRespCode: result.platRespCode
        });

        return result;
      } catch (parseError) {
        Logger.topPayError('创建订单响应解析失败', parseError, {
          orderId: request.orderId,
          responseText
        });
        throw new TopPayError(`TopPay响应解析失败: ${responseText}`, {
          orderId: request.orderId
        });
      }
    } catch (error) {
      if (error instanceof TopPayError) {
        throw error;
      }

      Logger.topPayError('创建订单请求失败', error, { orderId: request.orderId });
      throw new TopPayError(`TopPay API请求失败: ${error instanceof Error ? error.message : 'Unknown error'}`, {
        orderId: request.orderId
      });
    }
  }

  /**
   * 验证异步通知
   */
  verifyNotification(notification: TopPayNotification): boolean {
    const { platSign, ...params } = notification;
    
    // 按ASCII排序并拼接参数值
    const sortedKeys = Object.keys(params).sort();
    const signString = sortedKeys.map(key => params[key as keyof typeof params]).join('');
    
    return this.verifyWithPublicKey(signString, platSign);
  }

  /**
   * 格式化时间为TopPay要求的格式
   */
  private formatDateTime(date: Date): string {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');
    
    return `${year}${month}${day}${hours}${minutes}${seconds}`;
  }

  /**
   * 创建提现订单
   */
  async createPayoutOrder(request: CreatePayoutOrderRequest): Promise<TopPayResponse> {
    // 参数验证
    this.validateCreatePayoutOrderRequest(request);

    const params: any = {
      merchantCode: this.config.merchantCode,
      orderType: '0', // 法币(泰铢)交易 - 根据文档应为'0'
      method: 'Disbursement', // 收款方式 - 根据文档默认传Disbursement
      orderNum: request.orderId,
      money: request.amount.toFixed(2), // 使用money而不是payMoney
      feeType: '0', // 手续费类型：0-账内扣除，1-账外扣除
      number: request.receiverBankCard, // 客户银行卡号 - 使用number而不是transAccNo
      bankCode: request.bankCode, // 银行编码
      name: request.receiverName, // 客户名称
      notifyUrl: '', // 先设置为空，下面会填充
      dateTime: this.formatDateTime(new Date()),
      description: request.remark || '代付下单', // 描述 - 使用description而不是remark
    };

    // TopPay要求必须提供notifyUrl参数
    if (!this.config.notifyUrl) {
      throw new Error('notifyUrl未配置，请在环境变量中设置TOPPAY_NOTIFY_URL');
    }
    params.notifyUrl = this.config.notifyUrl;

    // 可选参数
    // mobile 和 email 是可选的，暂时不设置

    // 按ASCII排序并拼接参数值
    const sortedKeys = Object.keys(params).sort();
    const signString = sortedKeys.map(key => params[key as keyof typeof params]).join('');

    // 生成签名
    const sign = this.signWithPrivateKey(signString);

    const requestData = {
      ...params,
      sign,
    };

    Logger.topPayRequest('创建提现订单', {
      merchantCode: this.config.merchantCode,
      orderNum: requestData.orderNum,
      money: requestData.money,
      method: requestData.method,
      name: requestData.name
    }, { orderId: request.orderId });

    try {
      // 代付使用专门的API地址
      const payoutApiUrl = this.config.payoutApiUrl || 'https://tl-openapi.toppay.asia/gateway/cash';
      const response = await fetch(payoutApiUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestData),
      });

      if (!response.ok) {
        throw new TopPayError(`HTTP ${response.status}: ${response.statusText}`, {
          orderId: request.orderId,
          status: response.status
        });
      }

      const responseText = await response.text();
      Logger.topPayResponse('创建提现订单响应', responseText, { orderId: request.orderId });

      try {
        const result: TopPayResponse = JSON.parse(responseText);
        return result;
      } catch (jsonError) {
        Logger.error('TopPay提现订单响应JSON解析失败', jsonError, {
          orderId: request.orderId,
          responseText
        });
        throw new TopPayError(`响应格式错误: ${responseText}`, {
          orderId: request.orderId
        });
      }
    } catch (error) {
      if (error instanceof TopPayError) {
        throw error;
      }
      
      Logger.topPayError('创建提现订单网络错误', error, { orderId: request.orderId });
      throw new TopPayError(`网络请求失败: ${error instanceof Error ? error.message : 'Unknown error'}`, {
        orderId: request.orderId
      });
    }
  }

  /**
   * 验证提现订单创建参数
   */
  private validateCreatePayoutOrderRequest(request: CreatePayoutOrderRequest): void {
    if (!request.receiverName || request.receiverName.trim() === '') {
      throw new TopPayError('收款人姓名(receiverName)是必填项', {
        orderId: request.orderId,
        paymentMethod: request.paymentMethod
      });
    }

    if (!request.receiverBankCard || request.receiverBankCard.trim() === '') {
      throw new TopPayError('收款银行卡号(receiverBankCard)是必填项', {
        orderId: request.orderId,
        paymentMethod: request.paymentMethod
      });
    }

    if (!request.bankCode || request.bankCode.trim() === '') {
      throw new TopPayError('银行编码(bankCode)是必填项', {
        orderId: request.orderId,
        paymentMethod: request.paymentMethod
      });
    }

    if (request.amount <= 0) {
      throw new TopPayError('提现金额必须大于0', {
        orderId: request.orderId,
        amount: request.amount
      });
    }

    // 验证金额精度（TopPay支持两位小数）
    if (!/^\d+(\.\d{1,2})?$/.test(request.amount.toString())) {
      throw new TopPayError('提现金额最多支持两位小数', {
        orderId: request.orderId,
        amount: request.amount
      });
    }

    Logger.debug('提现订单创建参数验证通过', { orderId: request.orderId });
  }

  /**
   * 查询订单状态 - 根据TopPay API文档实现
   */
  async queryOrder(orderNum?: string, platOrderNum?: string): Promise<TopPayQueryResponse> {
    // 参数验证：商户订单号和平台订单号至少提供一个
    if (!orderNum && !platOrderNum) {
      throw new Error('商户订单号(orderNum)和平台订单号(platOrderNum)至少提供一个');
    }

    const params: any = {
      merchantCode: this.config.merchantCode,
      queryType: 'ORDER_QUERY', // 代收订单查询
      dateTime: this.formatDateTime(new Date()),
    };

    // 添加订单号参数
    if (orderNum) {
      params.orderNum = orderNum;
    }
    if (platOrderNum) {
      params.platOrderNum = platOrderNum;
    }

    // 按ASCII排序并拼接参数值
    const sortedKeys = Object.keys(params).sort();
    const signString = sortedKeys.map(key => params[key as keyof typeof params]).join('');
    const sign = this.signWithPrivateKey(signString);

    const requestData = {
      ...params,
      sign,
    };

    console.log('TopPay查询订单请求:', {
      merchantCode: this.config.merchantCode,
      orderNum,
      platOrderNum,
      queryType: params.queryType
    });

    try {
      const queryUrl = 'https://tl-openapi.toppay.asia/gateway/query';
      const response = await fetch(queryUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestData),
      });

      console.log('TopPay查询响应状态:', response.status);

      const responseText = await response.text();
      console.log('TopPay查询响应内容:', responseText);

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}, body: ${responseText}`);
      }

      try {
        const result: TopPayQueryResponse = JSON.parse(responseText);
        return result;
      } catch {
        throw new Error(`Failed to parse JSON response: ${responseText}`);
      }
    } catch (error) {
      throw new Error(`查询订单失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }
}

// 创建TopPay服务实例
export function createTopPayService(): TopPayService {
  const config: TopPayConfig = {
    merchantCode: process.env.TOPPAY_MERCHANT_CODE || '',
    privateKey: process.env.TOPPAY_PRIVATE_KEY || '',
    publicKey: process.env.TOPPAY_PUBLIC_KEY || '',
    apiUrl: process.env.TOPPAY_API_URL || 'https://tl-openapi.toppay.asia/gateway/prepaidOrder', // 充值订单URL
    payoutApiUrl: process.env.TOPPAY_PAYOUT_API_URL || 'https://tl-openapi.toppay.asia/gateway/cash', // 代付订单URL
    notifyUrl: process.env.TOPPAY_NOTIFY_URL || '',
    mchUserId: process.env.TOPPAY_MCH_USER_ID || '',
  };

  return new TopPayService(config);
}

// 检查TopPay配置是否完整
export function isTopPayConfigured(): boolean {
  const merchantCode = process.env.TOPPAY_MERCHANT_CODE;
  const privateKey = process.env.TOPPAY_PRIVATE_KEY;
  const publicKey = process.env.TOPPAY_PUBLIC_KEY;

  // 回调地址是可选的，所以不检查
  return !!(merchantCode && privateKey && publicKey);
}
